/*
 * location.h
 *
 *  Created on: Sep 13, 2011
 *      Author: zyq
 */

#ifndef LOCATION_H
#define LOCATION_H

#include <list>
#include <cv.h>

using std::list;
struct Rect
{
	long x1;
	long y1;
	long x2;
	long y2;
	long total;
};

struct Box
{
	long b1;
	long b2;
	long total;
};

/*
 * @brief       将灰度图片按照指定的长度和宽度进行缩放
 * @author      codekitten
 * @version     1.0
 * @data        2010.07.29
 * @param1 pSrc 原始图片指针
 * @param2 pDst 缩放后图片所存放的指针
 * @param3 l    缩放后图片的高度
 * @param4 w    缩放后图片的宽度
 * @return      操作错误代码
 * @pre         在函数执行前pSrc应该不为空指针
 * @post        在函数执行后pDst被创建
 * @exception   返回0代表成功,返回1代表pSrc为空指针
*/
char Resize(IplImage* pSrc, IplImage** pDst, long h, long w);

/*
 * @brief       将灰度图片进行预处理,主要是进行去噪和滤波
 * @author      codekitten
 * @version     1.0
 * @data        2010.07.29
 * @param1 pSrc 原始图片指针
 * @param2 pDst 预处理后图片所存放的指针
 * @return      操作错误代码
 * @pre         在函数执行前pSrc应该不为空指针,pSrc应该为灰度图片
 * @post        在函数执行后pDst被创建
 * @exception   返回0代表成功,返回1代表pSrc为空指针
*/
char PreProcess(IplImage* pSrc, IplImage** pDst);

char Diff(IplImage* pSrc, IplImage** pDst);
/*
 * @brief       对预处理后的灰度图片进行边缘检测,检测使用Sobel算子
 * @author      codekitten
 * @version     1.0
 * @data        2010.07.29
 * @param1 pSrc 原始图片指针
 * @param2 pDst 预处理后图片所存放的指针
 * @return      操作错误代码
 * @pre         在函数执行前pSrc应该不为空指针,pSrc应该为灰度图片
 * @post        在函数执行后pDst被创建
 * @exception   返回0代表成功,返回1代表pSrc为空指针
*/
char Edge(IplImage* pSrc, IplImage** pDst);

/*
 * @brief       对指定灰度图求直方图
 * @author      codekitten
 * @version     1.0
 * @data        2010.07.29
 * @param1 pSrc 原始图片指针
 * @param2 pHist所求得的直方图数组
 * @return      操作错误代码
 * @pre         在函数执行前pSrc和pHist应该不为空指针
 * @exception   返回0代表成功，返回1代表pSrc为空指针,返回2代表pHist为空指针
*/
char Hist(IplImage* pSrc, long* pHist);

/*
 * @brief       通过灰度直方图求其阈值
 * @author      codekitten
 * @version     1.0
 * @data        2010.07.29
 * @param1 pHist  直方图
 * @param2 length 直方图数组长度
 * @return      阈值
 * @pre         在函数执行前pHist应该不为空指针,pHist应该为单峰直方图,否则阈值不准
*/
long Threshold(long* pHist, long length);

/*
 * @brief       对灰度图进行二值化
 * @author      codekitten
 * @version     1.0
 * @data        2010.07.29
 * @param1 pSrc 原始图片指针
 * @param2 pDst 二值化后图片存放的指针
 * @return      操作错误代码
 * @pre         在函数执行前pSrc应该不为空指针
 * @post		在函数执行后pDst被创建
 * @exception   返回0代表成功，返回1代表pSrc为空指针
*/
char Binary(IplImage* pSrc, IplImage** pDst);

/*
 * @brief       创建图片的跳变表
 * @description 当像素点(i,j)为0,而(i+1, j)为1时,我们说它产生了一次跳变,则在跳变表的(i,j)处赋值为1,
 *              非跳变点处赋值0.二值化后的车牌图像,在车牌候选区域中的跳变点,往往多于其他非候选区域,
 *              因此我们可以通过跳变表的方式来获取车牌的候选区域
 * @author      codekitten
 * @version     1.0
 * @data        2010.07.29
 * @param1 pSrc 原始图片指针
 * @param2 pHopMap  所求得的跳变表数组
 * @return      操作错误代码
 * @pre         在函数执行前pSrc和pHopMap应该不为空指针,pSrc应该是二值化图片
 * @exception   返回0代表成功，返回1代表pSrc为空指针,返回2代表pHopMap为空指针
*/
char CreateHopMap(IplImage* pSrc, long* pHopMap);

/*
 * @brief       获取每行的跳变总数保存在一个行跳变数组中
 * @description 车牌区域,车灯区域,车标区域和通风口区域的跳变点数远远多于其他区域,当我们将每行的跳变
 *              点数求和的时候,就能够发现在这些地方会出现峰值.将此数据记录下来以利于候选区域的选取.
 * @author      codekitten
 * @version     1.0
 * @data        2010.07.29
 * @param1 pHopMap	所求得的图片跳变表数组
 * @param2 h        跳变表数组的高度
 * @param3 w        跳变表数组的宽度
 * @param4 pRowHops 行跳变数组
 * @return      操作错误代码
 * @pre         在函数执行前pHopMap和pRowHops应该不为空指针
 * @exception   返回0代表成功，返回1代表pHopMap为空指针,返回2代表pRowHops为空指针
*/
char GetRowHops(long* pHopMap, long h, long w, long* pRowHops);

/*
 * @brief       获取候选车牌区域的高度区间,保存在链表中
 * @author      codekitten
 * @version     1.0
 * @data        2010.07.29
 * @param1 pHopMap	所求得的图片跳变表数组
 * @param2 h        跳变表数组的高度
 * @param3 w        跳变表数组的宽度
 * @param4 blist    保存候选区域的链表
 * @return      操作错误代码
 * @pre         在函数执行前pHopMap应该不为空指针
 * @exception   返回0代表成功，返回1代表pHopMap为空指针
*/
char GetCandidatesFromHeight(long* pHopMap, long h, long w, std::list<Box>& blist);

/*
 * @brief       通过给定的数组,阈值和合并值,来划分区域,并将该区域保存在链表中
 * @author      codekitten
 * @version     1.0
 * @data        2010.07.29
 * @param1 arr	    需要划分的数组
 * @param2 length   需要划分的数组长度
 * @param3 thresh   阈值,将高于阈值的数组区域划分到一起
 * @param4 u		合并值,若两个区域之间的距离不大于u,则将两者合并为一个区域
 * @param5 blist    保存候选区域的链表
 * @return      操作错误代码
 * @pre         在函数执行前arr应该不为空指针
 * @exception   返回0代表成功，返回1代表arr为空指针
*/
char GetBox(long* arr, long length, long thresh, long u, std::list<Box>& blist);

/*
 * @brief       通过先前求出的候选车牌区域的高度区间，在其中确定宽度,保存在链表中
 * @author      codekitten
 * @version     1.0
 * @data        2010.07.29
 * @param1 pSrc	二值化图片指针
 * @param2 blist 车牌候选区域的宽度列表
 * @param3 blist 保存车牌整体候选区域的链表
 * @return      操作错误代码
 * @pre         在函数执行前pSrc应该不为空指针，blist应该处理完毕
 * @post		在函数执行后rlist保存车牌的整体候选区域
 * @exception   返回0代表成功，返回1代表pSrc为空指针
*/
char GetCandidatesFromWidth(IplImage* pSrc, std::list<Box>& blist, std::list<Rect>& rlist);

/*
 * @brief       在指定的高度区域内，求取列像素点的合，保存在列像素点数组中
 * @description 在指定的候选高度区域内,车牌出现的可能区域的像素点会比其他区域要高很多
 *              因此我们可以通过与跳变表划分类似的方式来划分宽度区域,这就需要列像素点
 *              数组
 * @author      codekitten
 * @version     1.0
 * @data        2010.07.29
 * @param1 pSrc	 二值化图片指针
 * @param2 y1    高度上限
 * @param3 y2    高度下限
 * @param4 pColumnPixels  列像素点数组
 * @return      操作错误代码
 * @pre         在函数执行前pSrc和pColumnPixels应该不为空指针
 * @post		在函数执行后pColumnPixels保存列像素点之和
 * @exception   返回0代表成功，返回1代表pSrc为空指针
*/
char GetColumnPixels(IplImage* pSrc, long y1, long y2, long* pColumnPixels);

/*
 * @brief       在候选区域中,获取总跳变点数之和
 * @author      codekitten
 * @version     1.0
 * @data        2010.07.29
 * @param1 pHopMap	 跳变表
 * @param2 h         图片高度
 * @param3 w         图片宽度
 * @param4 rect      候选区域
 * @return      操作错误代码
 * @pre         在函数执行前pHopMap应该不为空指针,rect中已保存候选区域
 * @post		在函数执行后总跳变点之和保存在Rect的total域中
 * @exception   返回0代表成功，返回1代表pHopMap为空指针
*/
char GetRectHops(long* pHopMap, long h ,long w, Rect& rect);

/*
 * @brief       在候选区域中选出真实车牌区域
 * @description 我们选择候选区域中跳变值之和最大的那个区域作为车牌的真实区域,其原因在于,
 *              对于干扰区域而言,在行跳变值的选择中,跳变值之和与真实区域相比相差不大,但
 *              干扰区域的跳变较为分散,而真实区域的跳变值十分集中,因此当缩小宽度范围之后,
 *              真实区域的的跳变值之和明显大于干扰区域,所以我们选择跳变值之和的大小作为最
 *              终选择标准
 * @author      codekitten
 * @version     1.0
 * @data        2010.07.29
 * @param1 rlist	 候选区域表
 * @param2 pHopMap   跳变表
 * @param3 rect      真实车牌区域
 * @pre         在函数执行前pHopMap应该不为空指针,rlist中已保存候选区域
*/
void Select(std::list<Rect>& rlist, long* pHopMap, Rect& rect);

#endif
